{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "virgin-shakespeare",
   "metadata": {},
   "source": [
    "# Visualizations"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "armed-trustee",
   "metadata": {},
   "source": [
    "The visualizations that power `interpret` use different renderers depending on the environment they are in. In most cases, the package will detect what kind of environment it is in and use the appropriat [renderer](https://github.com/interpretml/interpret/blob/683e632f4122af54eada2e214066de7be75bd7e0/python/interpret-core/interpret/provider/visualize.py#L25). There are times though when you want to forcefully select which one."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "impressed-tissue",
   "metadata": {},
   "source": [
    "<h2>Dash Renderer</h2>\n",
    "\n",
    "The Dash renderer is used for local environments such as running a Jupyter notebook on your laptop. It runs a Dash server, backed by Apache Flask in a separate process the first time its called by `interpret`.\n",
    "\n",
    "This provides access to both embedded visualizations within notebooks as well as the full dashboard. However, due to requiring a live Flask server, it cannot render in an offline notebook.\n",
    "\n",
    "See the source code for underestandings its configuration [here](https://github.com/interpretml/interpret/blob/683e632f4122af54eada2e214066de7be75bd7e0/python/interpret-core/interpret/provider/visualize.py#L149)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "grand-report",
   "metadata": {},
   "outputs": [],
   "source": [
    "from interpret import set_visualize_provider\n",
    "from interpret.provider import DashProvider\n",
    "set_visualize_provider(DashProvider.from_address(('127.0.0.1', 7001)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "alert-peeing",
   "metadata": {},
   "source": [
    "```{eval-rst}\n",
    ".. autoclass:: interpret.provider.DashProvider\n",
    "   :members:\n",
    "   :inherited-members:\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "adjacent-motorcycle",
   "metadata": {},
   "source": [
    "<h2>Inline Renderer</h2>\n",
    "\n",
    "The inline renderer is used for cloud environments access to flask servers are not always available. In most configurations, it injects JavaScript in each notebook cell, including the bundle.\n",
    "\n",
    "This does not allow for full dashboards, but it does allow offline support.\n",
    "\n",
    "See the source code for underestandings its configuration [here](https://github.com/interpretml/interpret/blob/683e632f4122af54eada2e214066de7be75bd7e0/python/interpret-core/interpret/provider/visualize.py#L192)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "assisted-bride",
   "metadata": {},
   "outputs": [],
   "source": [
    "from interpret import set_visualize_provider\n",
    "from interpret.provider import InlineProvider\n",
    "set_visualize_provider(InlineProvider())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "latin-brook",
   "metadata": {},
   "source": [
    "```{eval-rst}\n",
    ".. autoclass:: interpret.provider.InlineProvider\n",
    "   :members:\n",
    "   :inherited-members:\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "shaped-moses",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "smoking-comparative",
   "metadata": {},
   "source": [
    "<h2>Interactivity</h2>\n",
    "\n",
    "The visualizations consume the Interpret API, and is responsible\n",
    "for both displaying explanations and the underlying rendering infrastructure."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "light-steps",
   "metadata": {},
   "source": [
    "<h2>Visualizing with the show method</h2>\n",
    "\n",
    "Interpret exposes a top-level method `show`, of which acts as the surface for rendering explanation visualizations. This can produce either a drop down widget or dashboard depending on what's provided.\n",
    "\n",
    "<h2>Show a single explanation</h2>\n",
    "\n",
    "For basic use cases, it is good to show an explanation one at a time. The rendered widget will provide a dropdown to select between visualizations. For example, in the event of a global explanation, it will provide an overview, along with graphs for each feature as shown with the code below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "gross-river",
   "metadata": {},
   "outputs": [],
   "source": [
    "from interpret import set_visualize_provider\n",
    "from interpret.provider import InlineProvider\n",
    "set_visualize_provider(InlineProvider())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "threaded-conservative",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "from interpret.glassbox import ExplainableBoostingClassifier\n",
    "from interpret import show\n",
    "\n",
    "df = pd.read_csv(\n",
    "    \"https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data\",\n",
    "    header=None)\n",
    "df.columns = [\n",
    "    \"Age\", \"WorkClass\", \"fnlwgt\", \"Education\", \"EducationNum\",\n",
    "    \"MaritalStatus\", \"Occupation\", \"Relationship\", \"Race\", \"Gender\",\n",
    "    \"CapitalGain\", \"CapitalLoss\", \"HoursPerWeek\", \"NativeCountry\", \"Income\"\n",
    "]\n",
    "X = df.iloc[:, :-1]\n",
    "y = (df.iloc[:, -1] == \" >50K\").astype(int)\n",
    "\n",
    "seed = 42\n",
    "np.random.seed(seed)\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=seed)\n",
    "\n",
    "ebm = ExplainableBoostingClassifier()\n",
    "ebm.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "southeast-cemetery",
   "metadata": {},
   "outputs": [],
   "source": [
    "ebm_global = ebm.explain_global()\n",
    "show(ebm_global)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "vkrkskhflkjs",
   "metadata": {},
   "source": [
    "<br/>\n",
    "<br/>\n",
    "<br/>\n",
    "<br/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ahead-tobago",
   "metadata": {},
   "source": [
    "<h2>Show a specific visualization within an explanation</h2>\n",
    "\n",
    "Let's say you are after one specific visualization within an explanation, then you can specify it with a key as the subsequent function argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "social-module",
   "metadata": {},
   "outputs": [],
   "source": [
    "show(ebm_global, \"Age\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "qkfdlklkjss",
   "metadata": {},
   "source": [
    "<br/>\n",
    "<br/>\n",
    "<br/>\n",
    "<br/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "entitled-adjustment",
   "metadata": {},
   "source": [
    "<h2>Show multiple explanations for comparison</h2>\n",
    "\n",
    "If you running in a local environment (such as a running Python on your laptop), then `show` can expose a dashboard for comparison which can be invoked the in the following way (provide a list of explanations in the first argument):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "greater-bulgaria",
   "metadata": {},
   "outputs": [],
   "source": [
    "from interpret.glassbox import LogisticRegression\n",
    "\n",
    "# We have to transform categorical variables to use Logistic Regression\n",
    "X_train = pd.get_dummies(X_train, prefix_sep='.').astype(float)\n",
    "\n",
    "lr = LogisticRegression(random_state=seed, penalty='l1', solver='liblinear')\n",
    "lr.fit(X_train, y_train)\n",
    "\n",
    "lr_global = lr.explain_global()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "unauthorized-stereo",
   "metadata": {},
   "outputs": [],
   "source": [
    "show([ebm_global, lr_global])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bound-investing",
   "metadata": {},
   "source": [
    "<h2>Interpret API</h2>\n",
    "\n",
    "The API is responsible for standardizing ML interpretability\n",
    "explainers and explanations, providing a consistent interface for both users\n",
    "and developers. To support this, it also provides foundational top-level methods that support\n",
    "visualization and data access.\n",
    "\n",
    "**Explainers** are glassbox or blackbox algorithms that will produce an **explanation**, an artifact that is ready for visualizations or further data processing.\n",
    "\n",
    "<h2>Explainer</h2>\n",
    "\n",
    "An explainer will produce an explanation from its `.explain_*` method. These explanations normally provide an understanding of **global** model behavior or **local** individual predictions (`.explain_global` and `.explain_local` respectively).\n",
    "\n",
    "```{eval-rst}\n",
    ".. autoclass:: interpret.api.base.ExplainerMixin\n",
    "   :members:\n",
    "   :inherited-members:\n",
    "```\n",
    "\n",
    "<h2>Explanation</h2>\n",
    "\n",
    "An explanation is a self-contained object that help understands either its target model behavior, or a set of individual predictions. The explanation should provide access to visualizations through `.visualize`, and data processing the `.data` method. Both `.visualize` and `.data` should share the same function signature in terms of arguments.\n",
    "\n",
    "```{eval-rst}\n",
    ".. autoclass:: interpret.api.base.ExplanationMixin\n",
    "   :members:\n",
    "   :inherited-members:\n",
    "```\n",
    "\n",
    "<h2>Show</h2>\n",
    "\n",
    "The `show` method is used as a universal function that provides visualizations for whatever explanation(s) is provided in its arguments. Implementation-wise it will provide some visualization platform (i.e. a dashboard or widget) and expose the explanation(s)' visualizations as given by the `.visualize` call.\n"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
